using Microsoft.Extensions.Logging;

namespace hao_Common.Consul.Services
{
    /// <summary>
    /// Consul 服务发现实现类
    /// 提供服务发现和负载均衡功能
    /// </summary>
    public class ConsulServiceDiscovery : IServiceDiscovery
    {
        /// <summary>
        /// Consul 服务注册器，用于获取服务实例信息
        /// </summary>
        private readonly IConsulServiceRegistry _consulServiceRegistry;
        
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<ConsulServiceDiscovery> _logger;
        
        /// <summary>
        /// 随机数生成器，用于负载均衡算法
        /// </summary>
        private readonly Random _random = new();

        /// <summary>
        /// 构造函数
        /// 通过依赖注入获取所需的服务
        /// </summary>
        /// <param name="consulServiceRegistry">Consul 服务注册器</param>
        /// <param name="logger">日志记录器</param>
        public ConsulServiceDiscovery(
            IConsulServiceRegistry consulServiceRegistry,
            ILogger<ConsulServiceDiscovery> logger)
        {
            _consulServiceRegistry = consulServiceRegistry;
            _logger = logger;
        }

        /// <summary>
        /// 异步获取服务的访问地址
        /// 使用随机负载均衡算法从健康实例中选择一个
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>服务访问 URL，如果没有可用实例则返回 null</returns>
        public async Task<string?> GetServiceUrlAsync(string serviceName)
        {
            try
            {
                // 获取指定服务的所有健康实例
                var services = await _consulServiceRegistry.GetHealthyServicesAsync(serviceName);
                
                // 检查是否有可用的健康实例
                if (!services.Any())
                {
                    _logger.LogWarning("No healthy instances found for service: {ServiceName}", serviceName);
                    return null;
                }

                // 使用随机算法进行负载均衡
                // 从健康实例列表中随机选择一个
                var selectedService = services[_random.Next(services.Count)];
                var url = $"http://{selectedService.Service.Address}:{selectedService.Service.Port}";
                
                _logger.LogDebug("Selected service instance: {Url} for service: {ServiceName}", url, serviceName);
                return url;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error discovering service: {ServiceName}", serviceName);
                return null;
            }
        }

        /// <summary>
        /// 异步获取服务的所有健康实例
        /// 将 Consul 的 ServiceEntry 转换为自定义的 ServiceInstance 对象
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>健康的服务实例详细信息列表</returns>
        public async Task<List<ServiceInstance>> GetHealthyServiceInstancesAsync(string serviceName)
        {
            try
            {
                // 获取指定服务的所有健康实例
                var services = await _consulServiceRegistry.GetHealthyServicesAsync(serviceName);
                
                // 将 Consul 的 ServiceEntry 转换为自定义的 ServiceInstance
                return services.Select(s => new ServiceInstance
                {
                    ServiceId = s.Service.ID,                              // 服务实例 ID
                    ServiceName = s.Service.Service,                       // 服务名称
                    Address = s.Service.Address,                           // 服务地址
                    Port = s.Service.Port,                                 // 服务端口
                    Tags = s.Service.Tags ?? Array.Empty<string>()         // 服务标签（如果为 null 则使用空数组）
                }).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting healthy service instances for: {ServiceName}", serviceName);
                return new List<ServiceInstance>();
            }
        }
    }
}